package com.sparsearr.datastructures.ztr.sort;

import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;

import java.text.SimpleDateFormat;
import java.util.Arrays;
import java.util.Date;

/**
 * @Author: ZhaoTR
 * @Date: Created in 2025/5/31 20:20
 * @Description: 基数排序
 * @Version: 1.0
 */

public class RadixSort {
    private static final Logger logger = LogManager.getLogger(RadixSort.class);

    public static void main(String[] args) {
//        int[] arr = {53, 3, 542, 748, 14, 214};
        int[] arr = new int[80000];
        for (int i = 0; i < 80000; i++) {
            arr[i] = (int) (Math.random() * 8000000);
        }

        Date date = new Date();
        SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        String dateStr = simpleDateFormat.format(date);
        System.out.println("排序钱的时间是：" + dateStr);

        radixSort(arr);

        Date date1 = new Date();
        String dateStr1 = simpleDateFormat.format(date1);
        System.out.println("排序钱的时间是：" + dateStr1);
    }

    // 基数排序
    public static void radixSort(int[] arr) {
        // step 1. 得到数组中最大的位数
        int max = arr[0];

        for (int i = 1; i < arr.length; i++) {
            if (arr[i] > max) {
                max = arr[i];
            }
        }
        // 得到最大数是几位数
        int maxLength = (max + "").length();

        // 1. 针对每个元素的个位，进行排序处理
        // 定义一个二维数组，表示10个桶，每个桶就是一个一维数组
        // 10个桶，每个桶就是一个一维数组
        // 为了防止溢出，则每个 桶的容量为arr.length
        // 基数排序：空间换时间
        int[][] bucket = new int[10][arr.length];

        // 为了记录每个桶中，实际存放了多少个数据，我们定义一个一维数组来记录各个桶的每次放入的数据个数
        // bucketElementCounts[0] 记录的就是bucket【0】 放入的数据的个数
        int[] bucketElementCounts = new int[10];

        for (int i = 0, n = 1; i < maxLength; i++, n *= 10) {
            // 针对每个元素的对应的进行排序处理，第一次是个位，第二次是十位，第三次是百位
            for (int j = 0; j < arr.length; j++) {
                // 取出 数组中的每个元素 个位数
                int digitOfElement = arr[j] / n % 10;
                // 放入到对应的桶中
                bucket[digitOfElement][bucketElementCounts[digitOfElement]] = arr[j];
                bucketElementCounts[digitOfElement]++;
            }
            // 按照 桶的顺序，将桶中的数据，放入到原数组中
            int index = 0;
            //  遍历 桶, 将每个桶的数据，放入到原数组中
            for (int k = 0; k < bucketElementCounts.length; k++) {
                // 如果桶中有数据，我们才放入到原数组
                if (bucketElementCounts[k] != 0) {
                    // 循环该桶 即第K个 桶（即第k个一维数组）
                    for (int l = 0; l < bucketElementCounts[k]; l++) {
                        // 取出元素，放入到原数组arr
                        arr[index++] = bucket[k][l];
                    }
                }
                // 第i+1轮处理后，需要将每个 bucketElementCounts[k] =0
                bucketElementCounts[k] = 0;
            }
//            System.out.println("第" + (i + 1) + "轮，对个位数的排序：" + Arrays.toString(arr));
        }

//
//        // 第一轮 ：针对每个元素的个位进行排序处理
//        for (int j = 0; j < arr.length; j++) {
//            // 取出 数组中的每个元素 个位数
//            int digitOfElement = arr[j] % 10;
//            // 放入到对应的桶中
//            bucket[digitOfElement][bucketElementCounts[digitOfElement]] = arr[j];
//            bucketElementCounts[digitOfElement]++;
//        }
//
//        // 按照 桶的顺序，将桶中的数据，放入到原数组中
//        int index = 0;
//        //  遍历 桶, 将每个桶的数据，放入到原数组中
//        for (int k = 0; k < bucketElementCounts.length; k++) {
//            // 如果桶中有数据，我们才放入到原数组
//            if (bucketElementCounts[k] != 0) {
//                // 循环该桶 即第K个 桶（即第k个一维数组）
//                for (int l = 0; l < bucketElementCounts[k]; l++) {
//                    // 取出元素，放入到原数组arr
//                    arr[index++] = bucket[k][l];
//                }
//            }
//            // 第一轮处理后，需要将每个 bucketElementCounts[k] =0
//            bucketElementCounts[k] = 0;
//        }
//        System.out.println("第一轮，对个位数的排序：" + Arrays.toString(arr));
//
//        // ===========================
//
//        // 第二轮 ：针对每个元素的个位进行排序处理
//        for (int j = 0; j < arr.length; j++) {
//            // 取出 数组中的每个元素 十位数
//            int digitOfElement = arr[j] / 10 % 10;
//            // 放入到对应的桶中
//            bucket[digitOfElement][bucketElementCounts[digitOfElement]] = arr[j];
//            bucketElementCounts[digitOfElement]++;
//        }
//
//        // 按照 桶的顺序，将桶中的数据，放入到原数组中
//        index = 0;
//        //  遍历 桶, 将每个桶的数据，放入到原数组中
//        for (int k = 0; k < bucketElementCounts.length; k++) {
//            // 如果桶中有数据，我们才放入到原数组
//            if (bucketElementCounts[k] != 0) {
//                // 循环该桶 即第K个 桶（即第k个一维数组）
//                for (int l = 0; l < bucketElementCounts[k]; l++) {
//                    // 取出元素，放入到原数组arr
//                    arr[index++] = bucket[k][l];
//                }
//            }
//            bucketElementCounts[k] = 0;
//        }
//        System.out.println("第二轮，对个位数的排序：" + Arrays.toString(arr));
//
//
//        // ===========================
//
//        // 第三轮 ：针对每个元素的个位进行排序处理
//        for (int j = 0; j < arr.length; j++) {
//            // 取出 数组中的每个元素 百位数
//            int digitOfElement = arr[j] / 100;
//            // 放入到对应的桶中
//            bucket[digitOfElement][bucketElementCounts[digitOfElement]] = arr[j];
//            bucketElementCounts[digitOfElement]++;
//        }
//
//        // 按照 桶的顺序，将桶中的数据，放入到原数组中
//        index = 0;
//        //  遍历 桶, 将每个桶的数据，放入到原数组中
//        for (int k = 0; k < bucketElementCounts.length; k++) {
//            // 如果桶中有数据，我们才放入到原数组
//            if (bucketElementCounts[k] != 0) {
//                // 循环该桶 即第K个 桶（即第k个一维数组）
//                for (int l = 0; l < bucketElementCounts[k]; l++) {
//                    // 取出元素，放入到原数组arr
//                    arr[index++] = bucket[k][l];
//                }
//            }
//        }
//        System.out.println("第三轮，对个位数的排序：" + Arrays.toString(arr));

    }
}
